package com.lvmama.rhino.utils;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Array;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 签名校验
 * Created by lizhi.
 */
public class MD5Utils  {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(MD5Utils.class);
    
    private static final String MD5_SALT = "Vkd0U1UxSkdWbFZYYldoYVZtMDRlRmt5TVhOTmF6VllVbXhTYVdGc1dtRldhazVPVFZkSmVsSnVUazlXYlhoM1ZUTndWazFYU2xWWmVrWlBWMFZhUjFSclVsTlNSazQyVm14d2JGWnRZM2hXUldoSFpXczFWVlp1YUZOV1JscG9Wa1JLTTAxV2JGZGFSV3hQWWtkNFNWVXdWVFZOVmxZMlZtNWFWVTFyV2tOYVJrNHdWa1UxV1ZGcVJtaFhSbG8yVmtSR2EyRXlSWGRQVmxKUFVqSjNlRlpZY0dGaU1sSllVbXR3YUUxc1duTlhWbVJ2VlVkR1ZXSklaR3RXVkd4RFdWWk9NR0ZHVFhwUmJYaHBWbFZ3ZVZONlJrNU5SMUpaVm01Q1dHSlVSWGhXYWtKTFlqQnplVkpzYUdwTlJHd3dWakJvVjA1V1NraGpSelZVWVRKb01GbHJhRXRTVjBwSVkwWndUMDFxVlhsV01uUnZUVzFTY21OSVdrNVNSbG96V2xaV2MxUnNXa2hqU0ZKcFVrWndXbGt3YUVOa01rcDBUVlJHVkdWVWJIcFpNRll3WWxkS1NHRkhhR3hpVkVaM1dURmFiMk15UmxaaVNHeHBZbFJHY0ZwSE1ERmtSMGw0Vlc1R1lVMUhlRFZaYTJSM1V6RndkR1JFUm1wWFNFSXhXV3hqTlZaWFNraGpla3BZVWpOb00xWXhaR0ZrTVc5NFlrY3hhMkpzY0V4Wk1qRXdUVlpzVmxWdVVtRk5TR2Q1V1ZST1YyRkdiSFJQV0d4cVlURktlbGx0ZUhkU1YwVjZWbXR3YW1KWVVYaFpha3BMWkVkR1ZtTkZiR2xpVkVZeVZtdGpOVTFzYkZoVGJrWmhUVWQzZVZsVVRsZFRiRXBJVFZoT2FVMXNiM2xhUjNSelRtMUtkVlpVUWsxTmFrWXlWa1ZrZDJNeVRuVlJWRTVyWW14d1MxcFhNSGhsVm14WFZXNVNhRmRGV2xwWk1HUnJXVlpXU0dSRVJsVlRSWEF5V1d4YWQyVlhTa2hhUm5CaFlsUkdlbGt5ZEZOa01rcEZXa1JLYUdKWFVrdFZNVkYzVUZFOVBRPT0=";

    
    /**
     * 校验SIGN签名
     */
    @SuppressWarnings("unchecked")
    public static boolean check(HttpServletRequest request) {
        String sign = request.getParameter("lvtukey");
        if (StringUtils.isBlank(sign)) {
            return false;
        }

        Map<String, Object> parameterMap = request.getParameterMap();
        String originSign = getSign(parameterMap);
        String expectSign = DigestUtils.md5Hex(originSign + MD5_SALT);
        boolean checkResult = sign.equals(expectSign);
        if(!checkResult) {
            LOGGER.warn("md5签名校验失败, 接收参数为->" + GsonUtils.toJson(parameterMap)
                    + "\n预期的签名->" + expectSign);
        }
        return checkResult;
    }

    public static String getSign(Map<String, Object> parameterMap) {
        List<String> keys = new ArrayList<String>(parameterMap.keySet());
        keys.remove("IS_DEBUG"); //剔除IS_DEBUG、sign两个参数
        keys.remove("lvtukey");

        Collections.sort(keys); //键值ASCII码递增排序

        StringBuilder sb = new StringBuilder();
        for (String key : keys) {
            Object value = parameterMap.get(key);
            if (value == null) {
                continue;
            }
            if (value.getClass().isArray()) {
                for (int i = 0; i < Array.getLength(value); i++) {
                    String item = Array.get(value, i).toString();
                    sb.append(key).append('=').append(item).append('&');
                }
            } else if(value instanceof List) {
                List<Object> items = (List<Object>) value;
                for (Object item : items) {
                    sb.append(key).append('=').append(item.toString()).append('&');
                }
            } else {
                String str = value.toString();
                sb.append(key).append('=').append(str).append('&');
            }
        }
        if (sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }
    /**
     * 密码加密
     *
     * @param password
     * @return
     */
    public static String encode(String password) {
        try {
            //MD5加密
            String algorithm = "MD5";
            MessageDigest instance = MessageDigest.getInstance(algorithm);
            byte[] digest = instance.digest(password.getBytes());
            //十六进制加密
            char[] encodeHex = Hex.encodeHex(digest);
            return new String(encodeHex);
        }catch (Exception e) {

        }
        return null;
    }
}
